<?php

/*
 * This file is part of the symfony package.
 * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * sfWidgetFormSelectRadio represents radio HTML tags.
 *
 * @package    symfony
 * @subpackage widget
 * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
 * @version    SVN: $Id: sfWidgetFormSelectRadio.class.php 30762 2010-08-25 12:33:33Z fabien $
 */
class nlWidgetFormDoubleSelect extends sfWidgetFormChoiceBase
{
  /**
   * Constructor.
   *
   * Available options:
   *
   *  * choices:         An array of possible choices (required)
   *  * label_separator: The separator to use between the input radio and the label
   *  * separator:       The separator to use between each input radio
   *  * class:           The class to use for the main <ul> tag
   *  * formatter:       A callable to call to format the radio choices
   *                     The formatter callable receives the widget and the array of inputs as arguments
   *  * template:        The template to use when grouping option in groups (%group% %options%)
   *
   * @param array $options     An array of options
   * @param array $attributes  An array of default HTML attributes
   *
   * @see sfWidgetFormChoiceBase
   */
  protected function configure($options = array(), $attributes = array())
  {
    parent::configure($options, $attributes);

    $this->addOption('class', 'radio_list');
    $this->addOption('label_separator', '&nbsp;');
    $this->addOption('separator', "\n");
    $this->addOption('remove', true);
    $this->addOption('formatter', array($this, 'formatter'));
    $this->addOption('template', '%group% %options%');
  }

  /**
   * Renders the widget.
   *
   * @param  string $name        The element name
   * @param  string $value       The value selected in this widget
   * @param  array  $attributes  An array of HTML attributes to be merged with the default HTML attributes
   * @param  array  $errors      An array of errors for the field
   *
   * @return string An HTML tag string
   *
   * @see sfWidgetForm
   */
  public function render($name, $value = null, $attributes = array(), $errors = array())
  {
    if ('[]' != substr($name, -2))
    {
      $name .= '[]';
    }

    $choices = $this->getChoices();

    $widgetId = $this->generateId($name);

    if ($this->getOption('remove') !== true) {
      $selectRemove = ".clone().css('display', 'none')";
      $deselectRemove = "";
    } else {
      $selectRemove = '';
      $deselectRemove = "$(this).clone().removeClass('selected').appendTo('#{$widgetId}_left').click(select);";
    }


    $script = <<< JS
(function(){
var widget = $('#{$widgetId}'), li = $('#{$widgetId}_left li').click(select);

function deselect() {
var val = widget.val() || [],
    attr = this.getAttribute('value'),
    index = $.inArray(attr, val);

if (!$(this).hasClass('fading')) {
    {$deselectRemove}
    $(this).fadeOut(200, function(){\$(this).remove()}).addClass('fading');
    if (index >= 0) {
      val.splice(index, 1);
      widget.val(val);
    }
    li.filter(function(){return this.getAttribute('value') == attr}).removeClass('selected');
    }
}

function select(){
var val = widget.val() || [];
if ($.inArray(this.getAttribute('value'), val) === -1) {
    $(this).addClass('selected'){$selectRemove}.appendTo('#{$widgetId}_right').fadeIn(200).click(deselect);
    val.push(this.getAttribute('value'));
    widget.val(val);
}

}
$('#{$widgetId}_right li').click(deselect);

})();
JS;

    $style = <<< CSS
.doubleSelect ul {
  float: left;
  height: 300px;
  overflow: auto;
  display:block;
  width: 175px;
  border: 1px solid #aaa;
  margin-right: 5px;
  margin-left: 0;
}
.doubleSelect {width: 500px}

.doubleSelect ul li {
  margin: 0 10px;
  cursor: pointer;
  list-style: none;
  margin: 0 5px;
}

.doubleSelect ul li:hover {
  background: #eee !important;
}

.doubleSelect ul li.selected {
  opacity: 0.6;
  background: #fff !important;
}
.doubleSelect ul#{$widgetId}_right li.selected {
  opacity: 1;
}
CSS;


    return $this->formatChoices($name, $value, $choices, $attributes).
           $this->renderContentTag('script', $script, array('type' => 'text/javascript')).
           $this->renderContentTag('style', $style, array('type' => 'text/css'))
        ;

  }

  protected function formatChoices($name, $value, $choices, $attributes)
  {

    $inputs = array();
    $left_li = array();
    $right_li = array();
    $widgetId = $this->generateId($name);

    foreach ($choices as $key => $option)
    {

      $baseAttributes = array(
        'value' => self::escapeOnce($key),
      );

      if ($value !== null && in_array(strval($key), $value)) {
        $baseAttributes['class'] = 'selected';
        $baseAttributes['selected'] = 'selected';
      }

      $inputs[] = $this->renderContentTag('option', self::escapeOnce($option), $baseAttributes);
      if (!isset($baseAttributes['selected']) || $this->getOption('remove') !== true) {
        $left_li[] = $this->renderContentTag('li', self::escapeOnce($option), $baseAttributes);
      }
      if (isset($baseAttributes['selected'])) {
        $right_li[] = $this->renderContentTag('li', self::escapeOnce($option), $baseAttributes);
      }
    }

    $select = $this->renderContentTag('div',
      $this->renderContentTag('ul', implode("\n", $left_li), array('id' => $widgetId . '_left' )).
      $this->renderContentTag('ul', implode("\n", $right_li), array('id' => $widgetId . '_right')),
      array('class' => 'doubleSelect')
    );

    return $select.$this->renderContentTag('div',
      $this->renderContentTag('select',
        implode("\n", $inputs),
        array_merge(array('multiple'=>'multiple', 'name' => $name, 'id' => $widgetId), $attributes)
      ), array('style' => 'display:none;'));
  }

}
